<script setup>
  import { putSingleReadApi } from '@/api/message'
  import { CHAT_MSG_TYPE } from '@/contants/message'
  import { useUserStore } from '@/stores'
  import { formatTime } from '@/utils/time'
  import { computed, onMounted, onUnmounted } from 'vue'

  const emit = defineEmits(['loaded'])

  const userStore = useUserStore()

  const props = defineProps({
    // 单条消息对象
    item: Object,
    index: Number
  })

  const gotoDetailPage = (houseId) => {
    uni.navigateTo({
      url: `/pages/index/detail?id=${houseId}`
    })
  }

  const MAX_WIDTH = 490
  const MIN_WIDTH = 220
  const MAX_DURATION = 60
  // 计算语音条的宽度
  const voiceLabelWidth = computed(() => {
    const duration = props.item.time
    const width = (MAX_WIDTH * duration) / MAX_DURATION
    return width < MIN_WIDTH ? MIN_WIDTH : width
  })

  // 复制文本
  const copyText = (text) => {
    uni.setClipboardData({
      data: text,
      success: () => {}
    })
  }
  // 粘贴文本
  const pasteText = () => {
    if (props.item.type !== CHAT_MSG_TYPE.TEXT) return
    return new Promise((resolve, reject) => {
      uni.getClipboardData({
        success: (res) => {
          resolve(res.data)
        },
        fail: (error) => {
          reject(error)
        }
      })
    })
  }

  // 是否是自己
  const isSelf = computed(() => {
    return props.item.fromId === userStore.profile.userId
  })

  // 图片加载结束
  const onLoaded = () => {
    if (props.item.type === CHAT_MSG_TYPE.IMAGE) {
      emit('loaded')
    }
  }

  // 内置音频上下文对象
  let innerAudioCtx = null
  // 播放语音
  const onPlay = async (item) => {
    // 通知其他语音停止播放
    uni.$emit('play', props.index)
    if (!innerAudioCtx) {
      innerAudioCtx = uni.createInnerAudioContext()
      innerAudioCtx.src = item.content
      innerAudioCtx.play()
    } else {
      innerAudioCtx.stop()
      innerAudioCtx.play()
    }
    // 更新界面
    item.status = 1
    try {
      // 通知服务器更新语音为已读
      await putSingleReadApi(item.id)
    } catch (e) {
      setTimeout(async () => {
        await putSingleReadApi(item.id)
      }, 1000)
    }
  }
  // 组件挂载后
  onMounted(() => {
    if (props.item.type === CHAT_MSG_TYPE.VOICE) {
      uni.$on('play', (index) => {
        if (innerAudioCtx) {
          if (props.index !== index) {
            innerAudioCtx.stop()
          }
        }
      })
    }
  })
  // 组件卸载时
  onUnmounted(() => {
    if (props.item.type === CHAT_MSG_TYPE.VOICE) {
      // 解绑事件
      uni.$off('play')

      // 销毁语音上下文，释放资源
      if (innerAudioCtx) {
        innerAudioCtx.destroy()
        innerAudioCtx = null
      }
    }
  })
  // 暴漏出去
  defineExpose({
    pasteText
  })
</script>

<template>
  <!-- 卡片消息 -->
  <!-- 自己的 -->
  <block v-if="item.type === CHAT_MSG_TYPE.CARD">
    <block v-if="isSelf">
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view
        class="msg msg_card myself"
        @click="gotoDetailPage(item.content.houseId)"
      >
        <view class="card">
          <!-- 左侧图片 -->
          <image
            :src="item.content.headImage"
            mode="scaleToFill"
            class="image"
          />
          <!-- 右侧信息 -->
          <view class="info">
            <view class="main">
              <view class="info-title">{{ item.content.title }}</view>
              <view class="info-desc">{{ item.content.desc }}</view>
            </view>
            <view class="info-price">
              <text style="font-size: 24rpx">￥</text>
              <text style="font-size: 28rpx; font-weight: 600">{{ item.content.price }}</text>
              <text style="font-size: 24rpx">/月</text>
            </view>
          </view>
        </view>
        <image
          :src="userStore.profile.avatar"
          class="avatar"
          mode="widthFix"
        />
      </view>
    </block>
    <!-- 对方的 -->
    <block v-else>
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view
        class="msg msg_card other"
        @click="gotoDetailPage(item.content.houseId)"
      >
        <image
          :src="item.appUserVO.avatar"
          class="avatar"
          mode="widthFix"
        />
        <view class="card">
          <!-- 左侧图片 -->
          <image
            :src="item.content.headImage"
            mode="scaleToFill"
            class="image"
          />
          <!-- 右侧信息 -->
          <view class="info">
            <view class="main">
              <view class="info-title">{{ item.content.title }}</view>
              <view class="info-desc">{{ item.content.desc }}</view>
            </view>
            <view class="info-price">
              <text style="font-size: 24rpx">￥</text>
              <text style="font-size: 28rpx; font-weight: 600">{{ item.content.price }}</text>
              <text style="font-size: 24rpx">/月</text>
            </view>
          </view>
        </view>
      </view>
    </block>
  </block>

  <!-- 文字消息 -->
  <block v-if="item.type === CHAT_MSG_TYPE.TEXT">
    <!-- 自己的 -->
    <block v-if="isSelf">
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_text myself">
        <view
          class="text"
          @click.stop="copyText(item.content)"
          >{{ item.content }}</view
        >
        <image
          :src="userStore.profile.avatar"
          class="avatar"
          width="widthFix"
        />
      </view>
    </block>

    <!-- 对方的 -->
    <block v-else>
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_text other">
        <image
          :src="item.appUserVO.avatar"
          class="avatar"
          width="widthFix"
        />
        <view
          class="text"
          @click.stop="copyText(item.content)"
          >{{ item.content }}</view
        >
      </view>
    </block>
  </block>
  <!-- 图片消息 -->
  <block v-if="item.type === CHAT_MSG_TYPE.IMAGE">
    <block v-if="isSelf">
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_image myself">
        <image
          :src="item.content"
          mode="widthFix"
          class="image"
          @load="onLoaded"
        />
        <image
          :src="userStore.profile.avatar"
          class="avatar"
          mode="widthFix"
        />
      </view>
    </block>
    <!-- 对方的 -->
    <block v-else>
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_image other">
        <image
          :src="item.appUserVO.avatar"
          class="avatar"
          mode="widthFix"
        />
        <image
          :src="item.content"
          mode="widthFix"
          class="image"
          @load="onLoaded"
        />
      </view>
    </block>
  </block>
  <!-- 语音消息 -->
  <block v-if="item.type === CHAT_MSG_TYPE.VOICE">
    <!-- 自己的 -->
    <block v-if="isSelf">
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_voice myself">
        <view
          class="voice"
          :style="{ width: `${voiceLabelWidth}rpx` }"
          @click="onPlay(item)"
        >
          <text class="duration">{{ item.time }}''</text>
          <bit-icon size="28">&#xe8c4;</bit-icon>
        </view>
        <image
          :src="userStore.profile.avatar"
          class="avatar"
          mode="widthFix"
        />
      </view>
    </block>
    <!-- 对方的 -->
    <block v-else>
      <view class="time">{{ formatTime(item.createTime, 'MM月DD日 HH:mm') }}</view>
      <view class="msg msg_voice other">
        <image
          :src="item.appUserVO.avatar"
          class="avatar"
          mode="widthFix"
        />

        <view
          class="voice"
          :style="{ width: `${voiceLabelWidth}rpx` }"
          @click="onPlay(item)"
        >
          <bit-icon size="28">&#xe6b5;</bit-icon>
          <text class="duration">{{ item.time }}''</text>
          <text
            class="red_dot"
            v-if="item.status === 0"
          ></text>
        </view>
      </view>
    </block>
  </block>
</template>

<style lang="scss" scoped>
  // 卡片消息
  .msg_card {
    .card {
      display: flex;
      box-sizing: border-box;
      width: 490rpx;
      height: 200rpx;
      padding: 20rpx;
      background-color: #fff;
      border-radius: 16rpx;
      .image {
        width: 160rpx;
        height: 160rpx;
        border-radius: 16rpx;
        margin-right: 20rpx;
      }
      .info {
        display: flex;
        justify-content: space-between;
        flex: 1;
        flex-direction: column;
        &-title {
          font-size: var(--font-size-sm);
          color: #000;
        }
        &-desc {
          font-size: 20rpx;
          color: var(--text-color-middle);
        }
        &-price {
          color: #ff5c02;
        }
      }
    }
  }

  // 文字消息
  .msg_text {
    .text {
      box-sizing: border-box;
      width: fit-content;
      max-width: 490rpx;
      padding: 26rpx 20rpx;
      font-size: var(--font-size-sm);
      border-radius: 16rpx;
      color: var(--text-color-dark);
    }
    &.myself {
      .text {
        background-color: #d4e2fc;
      }
    }
    &.other {
      .text {
        background-color: #fff;
      }
    }
  }

  // 图片消息
  .msg_image {
    .image {
      max-width: 490rpx;
    }
  }
  // 语音消息
  .msg_voice {
    .voice {
      position: relative;
      display: flex;
      box-sizing: border-box;
      max-width: 490rpx;
      padding: 26rpx 20rpx;
      border-radius: 16rpx;
      .duration {
        font-size: var(--font-size-sm);
        color: var(--text-color-dark);
      }
      .red_dot {
        position: absolute;
        top: 50%;
        margin-top: -8rpx;
        width: 16rpx;
        height: 16rpx;
        background-color: #f50102;
        border-radius: 100%;
      }
    }
    &.myself {
      .voice {
        justify-content: flex-end;
        background-color: #d4e2fc;
        .red_dot {
          left: -20rpx;
        }
      }
      .duration {
        margin-right: 5rpx;
      }
    }
    &.other {
      .voice {
        background-color: #fff;
        .red_dot {
          right: -25rpx;
        }
      }
      .duration {
        margin-left: 5rpx;
      }
    }
  }
</style>
